/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package parse;


/**
 *
 * @author phong
 */
public class ComplexCategory extends Category {
    
    String opt;
    Category left, right;
            
    public ComplexCategory(String opt) {
        if (opt.equals("forward") || opt.equals(OPT_FW))
            this.opt = OPT_FW;
        else if (opt.equals("backward") || opt.equals(OPT_BW))
            this.opt = OPT_BW;
        else if (opt.equals("*"))
            this.opt = OPT_ANY;
        else 
            throw new Error("unknown opt");
        
        this.feature = "";
        this.left = null;
        this.right = null;
    }
    
    public ComplexCategory(String opt, String feature) {
        this(opt);
        this.feature = feature;
    }
    
    public ComplexCategory(String opt, Category left, Category right) {
        this(opt);
        this.left = left;
        this.right = right;
    }
    
    public ComplexCategory(String opt, String feature, Category left, Category right) {
        this(opt, left, right);
        this.feature = feature;
    }
    

    public void setLeft(Category node) {
        this.left = node;
    }
    
    public void setRight(Category node) {
        this.right = node;
    }
    
    public Category getLeft() {
        return this.left;
    }

    public Category getRight() {
        return this.right;
    }
    
    public String getOpt() {
        return this.opt;
    }
    
    @Override
    public String toString() {
        String str;
        if (this.left instanceof ComplexCategory)
            str = "(" + this.left.toString() + ")";
        else 
            str = this.left.toString();
        str += this.opt;
        if (this.right instanceof ComplexCategory)
            str += "(" + this.right.toString() + ")";
        else 
            str += this.right.toString();
        return str;
    }
    
    @Override
    public boolean equals(Object other) {
        if (other instanceof ComplexCategory) {
            ComplexCategory that = (ComplexCategory)other;
            return (this.opt.equals(OPT_ANY) || that.opt.equals(OPT_ANY) || this.opt.equals(that.opt)) && 
                    this.left.equals(that.left) && 
                    this.right.equals(that.right);
        }
        return false;
    }
    
    @Override
    public int hashCode() {
        return this.left.hashCode() * 31 + this.right.hashCode() * 17 + this.opt.hashCode();
    }
    
    @Override
    public Category leftMostRemove(Category cat) {
        if (this.left.equals(cat)) {
            return this.right;
        }
        else 
            return new ComplexCategory(this.opt, this.left.leftMostRemove(cat), this.right);
    }

    @Override
    public Category rightMostRemove(Category cat) {
        if (this.right.equals(cat)) {
            return this.left;
        }
        else 
            return new ComplexCategory(this.opt, this.left, this.right.rightMostRemove(cat));
    }

    @Override 
    public int numOfAllBasicCats() {
        return this.left.numOfAllBasicCats() + this.right.numOfAllBasicCats();
    }
}
